﻿// <copyright file="KinectInteractionLayer.cs" company="Ucaya">
// </copyright>
// <author>Ucaya</author>

namespace KinectExtensions.Controls
{
    #region

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Media;

    using KinectExtensions.Nui;
    using KinectExtensions.Services;

    #endregion

    /// <summary>
    ///   Hides mouse cursors and displays kinect cursor
    /// </summary>
    public class KinectInteractionLayer : Control, ICursorProvider, IOverlayProvider
    {
        #region Constants and Fields

        /// <summary>
        ///   BarVoiceCommands depedency property.
        /// </summary>
        public static readonly DependencyProperty BarVoiceCommandsProperty = DependencyProperty.Register("BarVoiceCommands", typeof(IEnumerable<string>), typeof(KinectInteractionLayer), null);

        /// <summary>
        ///   The items control.
        /// </summary>
        private ItemsControl itemsControl;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        ///   Initializes static members of the <see cref = "KinectInteractionLayer" /> class.
        /// </summary>
        static KinectInteractionLayer()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(KinectInteractionLayer), new FrameworkPropertyMetadata(typeof(KinectInteractionLayer)));
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref = "KinectInteractionLayer" /> class.
        /// </summary>
        public KinectInteractionLayer()
        {
            this.Loaded += this.KinectCursorLayer_Loaded;
        }

        #endregion

        #region Public Properties

        public IEnumerable<string> BarVoiceCommands
        {
            get
            {
                return (IEnumerable<string>)this.GetValue(BarVoiceCommandsProperty);
            }

            set
            {
                this.SetValue(BarVoiceCommandsProperty, value);
            }
        }

        /// <summary>
        ///   Gets or sets CursorService.
        /// </summary>
        [Import]
        public CursorService CursorService { get; set; }

        /// <summary>
        ///   Gets HandPositions.
        /// </summary>
        public IEnumerable<HandPosition> HandPositions
        {
            get
            {
                return ServiceLocator.Instance.GetExportedValue<HandTrackingService>().HandPositions;
            }
        }

        [Import]
        public InteractionManager InteractionManager { get; set; }

        [Import]
        public OverlayService OverlayService { get; private set; }

        #endregion

        #region Public Methods

        /// <summary>
        ///   The get cursor.
        /// </summary>
        /// <param name = "position">
        ///   The position.
        /// </param>
        /// <returns>
        /// </returns>
        public ICursor GetCursor(HandPosition position)
        {
            if (this.itemsControl == null)
            {
                return null;
            }

            var contentPresenter = (ContentPresenter)this.itemsControl.ItemContainerGenerator.ContainerFromItem(position);
            if (contentPresenter == null || VisualTreeHelper.GetChildrenCount(contentPresenter) == 0)
            {
                return null;
            }

            return VisualTreeHelper.GetChild(contentPresenter, 0) as ICursor;
        }

        public Panel GetOverlayLayer()
        {
            return this.GetTemplateChild("overlay") as Panel;
        }

        /// <summary>
        ///   The on apply template.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.itemsControl = this.GetTemplateChild("ItemsControl") as ItemsControl;
        }

        #endregion

        #region Methods

        private void InteractionManager_CurrentInteractionModeChanged(object sender, EventArgs e)
        {
            this.RefreshInteraction();

            if (this.InteractionManager.CurrentInteractionMode == Interactions.Voice)
            {
                var voiceService = ServiceLocator.Instance.GetExportedValue<VoiceService>();

                this.SetBinding(BarVoiceCommandsProperty, new Binding("BarHintText") { Source = voiceService });
            }
        }

        /// <summary>
        ///   The kinect cursor layer_ loaded.
        /// </summary>
        /// <param name = "sender">
        ///   The sender.
        /// </param>
        /// <param name = "e">
        ///   The e.
        /// </param>
        private void KinectCursorLayer_Loaded(object sender, RoutedEventArgs e)
        {
            ServiceLocator.Instance.SatisfyImportsOnce(this);
            this.CursorService.CursorProvider = this;
            this.OverlayService.OverlayProvider = this;
            this.InteractionManager.CurrentInteractionModeChanged += this.InteractionManager_CurrentInteractionModeChanged;

            this.RefreshInteraction();
        }

        private void RefreshInteraction()
        {
            bool success = VisualStateManager.GoToState(this, this.InteractionManager.CurrentInteractionMode + "State", true);
        }

        #endregion
    }
}